/*
 * Class server.java
 * @author Guillermo Moraleda
 * @author Loles Salmeron
 *
 * Diffie-Hellman key exchange algorithm
 * over a TCP Socket.
 *
 */
package kau.cs.lab.connection;

import java.io.*;
import java.net.*;
import java.math.BigInteger;
import kau.cs.lab.blowfish.Blowfish;

class server {

    private final static int q = 23;
    private final static int g = 5;
    private static int A;
    private static int B;
    private static int b;
    private static BigInteger powresult;
    private static BigInteger big_b;
    private static BigInteger big_q;
    private static int key;

    public static void main(String argv[]) throws Exception {

        //Diffie-Hellman Algorithm

        b = (int) Math.round(Math.random() * 100);
        while (b >= q) {
            b = b - q;
        }
        B = (int) (Math.pow(g, b) % q);
        System.out.println("q = " + q + "\ng = " + g + "\nb = " + b + "\nB = " + B);

        ServerSocket welcomeSocket = new ServerSocket(6789);
        Socket connectionSocket = welcomeSocket.accept();
        BufferedReader inFromClient =
                new BufferedReader(new InputStreamReader(connectionSocket.getInputStream()));
        PrintWriter outToClient = new PrintWriter(connectionSocket.getOutputStream(), true);
        //DataOutputStream outToClient = new DataOutputStream(connectionSocket.getOutputStream());

        //Send B = g^b mod p
        outToClient.println(String.valueOf(B));


        //Receive A = g^a mod p
        A = Integer.parseInt(inFromClient.readLine());

        System.out.println("A = " + A);

        //Create Key
        powresult = new BigInteger(Integer.toString(A));
        big_b = new BigInteger(Integer.toString(b));
        big_q = new BigInteger(Integer.toString(q));
        key = (powresult.modPow(big_b, big_q)).intValue();

        //Create BlowFish instance
        Blowfish bf = new Blowfish();
        bf.Blowfish_Init(intToByteArray(key));

        //Read from client
        String message = inFromClient.readLine();
        //Decrypt
        byte[] encrypted = message.getBytes();
        System.out.println(encrypted);
        System.out.println("Cipher Text Hex :" + Blowfish.getHexString(encrypted));
        System.out.println("Key             :" + key);
        byte[] decrypted = bf.crypt(encrypted, false);
        System.out.println("Plain Text      :" + new String(decrypted));

        //Encrypt new message and send to client
        message = "Server:->" + message;
        byte[] encrypted2 = bf.crypt(message.getBytes(), true);
        outToClient.println(new String(encrypted2));

        //Close sockets
        connectionSocket.close();
        welcomeSocket.close();
    }

    public static final byte[] intToByteArray(int value) {
        return new byte[]{
                    (byte) (value >>> 24),
                    (byte) (value >>> 16),
                    (byte) (value >>> 8),
                    (byte) value};
    }
}


